Godspeed Express Plugin
The Godspeed Express Plugin is a core component of the Godspeed framework, integrating with the popular Express.js framework to handle HTTP events. This plugin provides seamless, schema-driven development for HTTP-based event handling, offering features like input/output validation, authentication, and Swagger/GraphQL spec generation. This flexible tool allows developers to build robust, modular, and configurable server-side applications in Node.js.
Explore the Plugin Source Code here
Plugin Features
Read More about the Features of Express Plugin here
How to Use
- Create a godspeed project from the CLI and by default the Express plugin is integrated into your project if not, add the plugin from the CLI and select the
@godspeedsystems/plugins-express-as-http
to integrate the plugin.
> godspeed plugin add
,_, ╔════════════════════════════════════╗
(o,o) ║ Welcome to Godspeed ║
({___}) ║ World's First Meta Framework ║
" " ╚════════════════════════════════════╝
? Please select godspeed plugin to install: (Press <space> to select, <Up and Down> to move rows)
┌────┬───────────────────────────────────┬─────────────────────────────────────────────────────────────────┐
│ │ Name │ Description │
├────┼───────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ ❯◯ │ express-as-http │ Godspeed event source plugin for express as http server │
├────┼───────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ ◯ │ aws-as-datasource │ aws as datasource plugin for Godspeed Framework │
├────┼───────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ ◯ │ mailer-as-datasource │ mailer as datasource plugin for Godspeed Framework │
├────┼───────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ ◯ │ excel-as-datasource │ excel as datasource plugin for Godspeed Framework │
├────┼───────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ ◯ │ kafka-as-datasource-as-eventsource│ kafka as datasource-as-eventsource plugin for Godspeed Framework│
└────┴───────────────────────────────────┴─────────────────────────────────────────────────────────────────┘
- You will find two files added in your project related to the Express plugin at
src/eventsources/types/express.ts
- the type file andsrc/eventsources/http.yaml
- the instance file.
Type File
eventsources/types/express.ts
You generally will not need to touch this file, unless you want to extend or customize the Express functionality
import { ExpressEventSource } from '@godspeedsystems/plugins-express-as-http';
export default ExpressEventSource;This is the file generated by the plugin add command. In case you want to customise the Express plugin to add new features like some middlewares not currently supported by the default plugin implementation, you can modify this
type
file in your project. Checkout the section how to create custom event source
Instance file
src/eventsources/http.yaml
You can create as many Express instances in your project as http1, http2 and so on. The instance files keep configurations of each instance for the given type of plugin (in following example it is of type: express
)
Default Instance (yaml) File of Express Plugin
type: express
port: 3000
base_url: /api/v1 #the base url of the http service
#Bassic swagger setup
docs:
endpoint: /api-docs # the url on which the service will start
info: # info object as per swagger 3.0 spec
title: Sample Godspeed App
version: 1.1.0
summary: some http calls
description: lets play with Godspeed
contact:
name: API Support
url: 'http://www.myfintech.com/support'
email: support@myfintech.com
license:
name: Apache 2.0
url: 'https://www.apache.org/licenses/LICENSE-2.0.html'
servers:
- url: 'http://localhost:3000'
description: Public API server
- url: 'http://localhost:3001'
description: Internal API server
request_body_limit: 20000 # maximum size of the request body (in bytes)
file_size_limit: 50000 # How big a file can be uploaded (in bytes) Default is 50 MB.
#jwt settings to run by default on every event (endpoint)
authn:
jwt:
secretOrKey: mysecret #the secret
audience: mycompany #aud in jwt token
issuer: mycompany #iss in jwt token
# authorization policies to run by default on every event
# Uncomment this to start checking user roles.
# This will require jwt to be setup, or another middleware to setup the user information in inputs
authz:
- id: check_user_role
fn: com.gs.transform
args: <%inputs.user.role === 'admin'%> #an inline JS based check of user role
# validation error handling, to transform error responses on wrong input or response
on_request_validation_error: validations.request.standardResponse
on_response_validation_error:
- id: response_validation_error_handler
fn: com.gs.return
args: <%inputs%>
HTTP Event Schema Format
All types of events in Godspeed follow a standard format, with only the first line of the event definition changing as per the eventsource type. In case of http, the following structure represents the applicable composition of an event. Specifying the event schema here, not only validates your input and response, handles authentication and authorization, but also generates your swagger spec and Graphql schema.
http.<method>./<endpoint_url>: #the base_url is prepended to this endpoint path when the service runs
fn: path.to.function #the event handler: could be a typescript, javascript or YAML function
# Swagger params
body: #requestBody - applicable for POST, PUT requests
params: #headers, query, path params as per swagger spec
responses: #response structure as per swagger spec
id:
operationId:
tags:
summary:
description:
#OTHER PARAMS
# more common parameters to all event types across all event sources, as well applicable to http events
on_request_validation_error:
on_response_validation_error:
authn:
authz:
log:
attributes:
- The event YAML defines properties for handling specific HTTP requests within the Express app. In the YAML,
<method>
should be replaced with actual HTTP methods such asGET, POST, PUT, or DELETE
, specifying how the app handles those requests. The<endpoint_url>
field should contain the API URL for the respective HTTP route. - A function (event handler) will be triggered on sending a request to the respective url. The functions are created under
src/functions/
.
Get Started by writing an event and workflow for Express
You can store one or more events in each YAML file stored in the events
folder. The files can be organized and stored in any folder structure.
src/events/sample.yaml
Sample Event
http.get./sample_api:
fn: sample #redirects to src/functions/sample.yaml
authn: false #to disable global default setting of JWT authn, say authn: false.
# authz: overriden.custom.authz_fn #here you can add path to a JS/TS/YAML function file or put inline YAML workflow for custom authz
id: # Swagger id. by default calculated from the event URI
operationId: #Swagger if not set explicitly, the `id` is used. if `id` not set `summary` is used. If that is also not set, `${method}_${apiEndPoint}` with whitespace replaced by `_` is used
tags: #swagger tags. by default, a tag is generated from the `folder_path+event_file_name`
summary: #swagger description
description: #swaggers summary
body: #swagger spec equivalent to swagger's requestBody
content:
application/json:
schema:
type: object
properties:
name:
type: string
message:
type: string
params: #swagger params
- in: query
name: user
required: true
schema:
type: string
responses: #swagger spec of responses
200:
content:
application/json:
schema:
type: string
log: #custom attributes to add with log statements wherever they are printed by the handlers called by this event
attributes:
event_name: sample
# on_request_validation_error:
# on_response_validation_error:
Event Handler or Workflow: (TS/JS based)
The meta-framework supports pure functions. This means they take JSON as input and return JSON as output, irrespective of the eventsource from where the event is captured and response returned. Hereby sharing a typescript function which shows all that you get in your event handler workflow when an event is captured by any event source. The generic input structure is constant whether for Express, Fastify, Kafka, Salesforce, Socket etc.
import { GSContext, PlainObject } from "@godspeedsystems/core";
export default function (ctx: GSContext, args: PlainObject) {
//@ts-ignore
const {
inputs: {
data: {
params, body, query, user, headers, files
}
},
childLogger,
logger,
outputs,
functions,
datasources,
config,
mappings
}: {
inputs: {
data: {
params: PlainObject,
body: PlainObject,
query: PlainObject,
user: PlainObject,
headers: PlainObject,
files: any
}
},
childLogger: any, // Pino logger with log.attributes set (which you saw in eventsource, event configurations as well)
outputs: PlainObject,
logger: any, //Pino logger (Plain jain Pino logger without any custom log attributes)
functions: PlainObject, // The functions in the `src/functions` folder
datasources: PlainObject, // The clients of the datasources you have configured in this proejct
config: PlainObject, //Plain JSON of the config folder as per the node-config module
mappings: PlainObject //Plain JSON loaded from the mappings folder
} = ctx;
// Will print with workflow_name and task_id attributes
childLogger.info('Server is running healthy');
// Will print without workflow_name and task_id attributes
logger.info('Inputs object \n user %o query %o body %o headers %o params %o', user, query, body, headers, params);
logger.info('Outputs object has outputs from previous tasks with given ids %o', Object.keys(outputs));
logger.info('Datasources object has following datasource clients %o', Object.keys(datasources));
logger.info('Total functions found in the project %s', Object.keys(functions).length)
return {
data: 'Its working! ' + body.name,
code: 200,
success: true,
headers: {
custom_response_header: 'something'
}
}
}
Event Handlers: YAML based
Same response in a yaml workflow.
summary: Returning response
tasks:
- id: first_task
fn: com.gs.return
args:
data: <% 'Its working + inputs.body.name %>
headers:
custom_response_header: something
# code: 200 Default value from com.gs.return is success and code is 200
Setting Base Url
The base url is set in datasources/api.yaml
type: axios
base_url: /api/v1
Configuring JWT
You can configure JWT settings within the eventsources/http.yaml. Here's an example of such a configuration:
type: express
authn:
jwt:
issuer: <% config.issuer %> # must be equal to the key iss in your jwt token
audience: <% config.audience %> # must be equal to the key aud in your jwt token
secretOrKey: <% config.secret %>
Note: In order to add OAUTH2 you will need to customize the Express event source as it is not currently supported in the default implementation. Your PR Is welcome!
Configuring OAuth2
You can configure OAUth2 settings within the eventsources/http.yaml. Here's an example of such a configuration
Uploading files
The Express plugin allows you to upload your files
The default file size accepted is 50MB. If you wish to specify a custom file size, you can modify the value in "./src/eventsources/http.yaml
".
Example- Event to Upload file
Example Workflow to handle the uploaded files
export default function (ctx: GSContext) {
// You will get files in the ctx.inputs, along with params, body, query, user, headers
const { files: { panCardFile } } = ctx.inputs.data;
//do something like upload to S3
return {
data: 'Uploaded',
success: true,
code: 201,
//headers: {}
}
}
Example success response
Upon successful upload of the file in Postman, an autogenerated tmp
folder is created within the project directory, containing the uploaded file.
Plugin Components
Click here to read more about the Key Components of Express Plugin.